package com.springmq.mq.juc;

import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @ClassName : Demo4
 * @Author : lby
 * @Date: 2021/2/4 14:47
 * @Description : 读写锁
 */
public class Demo4 {
    public static void main(String[] args) {
        Demo4Test demo4Test = new Demo4Test();
        /**
         * 执行写操作
         */
        for (int i = 1; i < 5; i++) {
            final String  temp;
                temp = String.valueOf(i);
                ThreadFactory threadFactory = r -> new Thread(r, "aaaaa" + r.hashCode());
                ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, 10, TimeUnit.MINUTES, new SynchronousQueue<Runnable>(), threadFactory);
                executor.execute(()->{
                    demo4Test.writeTest(temp,temp);
                });
        }
        /**
         * 执行读操作
         */
        for (int i = 1; i < 5; i++) {
            final String  temp;
                temp = String.valueOf(i);
                ThreadFactory threadFactory = r -> new Thread(r, "aaaaa" + r.hashCode());
                ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, 10, TimeUnit.MINUTES, new SynchronousQueue<Runnable>(), threadFactory);
                executor.execute(()->{
                    demo4Test.readTest(temp);
                });
        }
    }
}


@Slf4j
class Demo4Test{
    /**
     * 模拟缓存
     */
    Map<Object,Object> map=new HashMap<>();

    /**
     * 由于只允许一个线程同时写，允许多个线程同时读，所以需要对每个线程加入读写锁
     */
    ReadWriteLock  readWriteLock = new ReentrantReadWriteLock();


    /**
     * 读(同时可以允许多个人读)
     */
    void readTest(String key){
        // 读之前加入读锁
        readWriteLock.readLock().lock();
        Object o = null;
        try {
            o = map.get(key);
            log.info("读取数据:{}",o);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            readWriteLock.readLock().unlock();
        }

    }

    /**
     * 写（同时只能一个人写）
     */
    void writeTest(String key,String value){
        // 写之前加入写锁
        readWriteLock.writeLock().lock();
        try {
            map.put(key,value);
            log.info("写入数据:{}",value);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            readWriteLock.writeLock().unlock();
        }

    }
}
